#include "server.h"

#include <QtDebug>
#include <QSqlField>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>

server::server(QObject *parent) : QObject(parent), mysql(QSqlDatabase::addDatabase("QMYSQL"))
{
    tcpserver = new QTcpServer(this);
    if(tcpserver->listen(QHostAddress::Any, 54321))
    {
        qDebug() << "绑定成功";
    }
    else
    {
        qDebug() << "绑定失败:" << tcpserver->errorString();
    }
    qDebug() << QSqlDatabase::drivers();

    mysql.setHostName("127.0.0.1");
    mysql.setPort(3306);
    mysql.setPassword("667188");
    mysql.setUserName("root");
    mysql.setDatabaseName("qt");
    if(mysql.open())
    {
        qDebug() << "数据库连接成功";
    }
    else
    {
        qDebug() << "数据库连接失败";
        return;
    }
    connect(tcpserver, SIGNAL(newConnection()), this, SLOT(handleconnection()));
    userlist.clear();
}
/*
 * +----+------+--------+----------+------+
| id | name | passwd | question | sex  |
+----+------+--------+----------+------+
| 1  | zhou | 123456 | 仲恺     | man  |
+----+------+--------+----------+------+

 *
 *
 *
 *
 *
 * */
// 处理登录请求
void server::handle_signin(QTcpSocket *fd, const QJsonObject &obj)
{
    qDebug() << "正在处理登录信息:" << obj;
    QString userid = obj.value("userid").toString();
    QString passwd = obj.value("passwd").toString();
    QSqlQuery  ret = mysql.exec(QString("select * from user where id = '%1';").arg(userid));
//    QSqlRecord retrecord = ret.record();

//    qDebug() << ret.isActive();
//    qDebug() << ret.isValid();
//    qDebug() << ret.next();
//    qDebug() << ret.next();
//    qDebug() << "=======================";
//    qDebug() << retrecord.isEmpty();
//    qDebug() << retrecord.count();
//    qDebug() << retrecord.fieldName(0);
//    qDebug() << retrecord.field(0);
//    qDebug() <<
    bool hasret = false;
    QStringList retlist;
    while (ret.next()) {
        hasret = true;
        for(int i = 0; i < 5; i++)
            retlist << ret.record().value(i).toString();
    }

    QJsonObject ans_obj;
    ans_obj.insert("type", "user_signin");
    if(hasret && passwd == retlist[2])
    {
        ans_obj.insert("isallowed", true);
        ans_obj.insert("username", retlist[1]);//回发昵称
        ans_obj.insert("userid", retlist[0]);//回发id
        ans_obj.insert("sex", retlist[4]);//回发性别
        userlist << usernode(fd, retlist[0], retlist[1]); //把新登录的用户写在线用户链表
        qDebug() << "数据库查询数据成功";

        QJsonDocument ans_js(ans_obj);
        fd->write(ans_js.toJson());

        brodcastNewclient(fd);
    }
    else
    {
        ans_obj.insert("isallowed", false);
        ans_obj.insert("errmessage", ret.lastError().text());
        qDebug() << "数据库查询数据失败";

        QJsonDocument ans_js(ans_obj);
        fd->write(ans_js.toJson());
    }

}

void server::handle_signup(QTcpSocket *fd, const QJsonObject &obj)
{
    qDebug() << "正在处理注册信息:" << obj;
    QString userid = obj.value("userid").toString();
    QString username = obj.value("username").toString();
    QString passwd = obj.value("passwd").toString();
    QString question = obj.value("question").toString();
    QString sex = obj.value("sex").toString();

    QSqlQuery ret = mysql.exec(QString
                   ("INSERT INTO user VALUES('%1', '%2', '%3', '%4', '%5');")
                               .arg(userid).arg(username).arg(passwd).arg(question).arg(sex));

    QJsonObject ans_obj;
    ans_obj.insert("type", "user_signup");
    ans_obj.insert("isallowed", ret.isActive());
    QString errmess = ret.isActive() ? "" : ret.lastError().text();
    ans_obj.insert("errmessage", errmess);
    qDebug() << ans_obj;
    fd->write(QJsonDocument(ans_obj).toJson());

}

void server::handle_getfriendslist(QTcpSocket *fd)
{
    QJsonObject ans_obj;
    ans_obj.insert("type", "getfriendslist");

    QJsonObject friendslist;
    for(int i = 0; i < userlist.size(); i++)
    {
        friendslist.insert(userlist.at(i).userid, userlist.at(i).username);
    }
    ans_obj.insert("users", friendslist);

    fd->write(QJsonDocument(ans_obj).toJson());
}

void server::handle_sendmessage(QTcpSocket *fd, const QJsonObject &obj)
{
    qDebug() << obj;
    QString sender = obj.value("sender").toString();
    QString recver = obj.value("recver").toString();

    QJsonObject forward;
    forward.insert("type","forwardmsg");
    forward.insert("msgtype", obj.value("msgtype"));
    forward.insert("sender", sender);
    forward.insert("message", obj.value("message"));
    for(int i = 0; i < userlist.size(); i++)
    {
        if(recver == userlist[i].userid)
        {
            qDebug() << "找到接收者";
            userlist[i].userfd->write(QJsonDocument(forward).toJson());
            return;
        }
    }
    qDebug() << "没有找接收者";
}

void server::handle_findpasswd(QTcpSocket *fd, const QJsonObject &obj)
{
    QString userid = obj.value("userid").toString();
    QString answer = obj.value("answer").toString();
    QSqlQuery ret = mysql.exec(QString("select passwd,question from user where id=%1;").arg(userid));

    QJsonObject ans_obj;
    ans_obj.insert("type", "findpasswd");

    if(!ret.isActive())
    {
        ans_obj.insert("isallowed", false);
        ans_obj.insert("errmessage", ret.lastError().text());
    }
    else
    {
        if(ret.next())
        {
            if(ret.record().value(1).toString() == answer)
            {
                ans_obj.insert("isallowed", true);
                ans_obj.insert("passwd", ret.record().value(0).toString());
            }
            else
            {
                ans_obj.insert("isallowed", false);
                ans_obj.insert("errmessage", "密保错误");
            }
        }
        else
        {
            ans_obj.insert("isallowed", false);
            ans_obj.insert("errmessage", "没有该账号");
        }
    }

    fd->write(QJsonDocument(ans_obj).toJson());
}

void server::handle_cancel_signin(QTcpSocket *fd)
{
    for(int i = 0; i < userlist.size(); i++)
    {
        if(userlist.at(i).userfd == fd)
        {
            userlist.removeAt(i);
        }
    }
}

server::~server()
{
    mysql.close();
}

void server::brodcastNewclient(QTcpSocket *fd)
{
    QJsonObject obj;
    obj.insert("type", "newclient");

    for(int i = 0; i < userlist.size(); i++)
    {
        if(userlist.at(i).userfd == fd)
            continue;

        userlist.at(i).userfd->write(QJsonDocument(obj).toJson());
    }
}

//处理新的连接请求
void server::handleconnection()
{
    QTcpSocket *newsocket = tcpserver->nextPendingConnection();
    connect(newsocket, SIGNAL(readyRead()), this, SLOT(handleread()));
    connect(newsocket, SIGNAL(disconnected()), this, SLOT(handledisconnect()));
}

//处理新的断开连接
void server::handledisconnect()
{
    QTcpSocket *tobeclose = qobject_cast<QTcpSocket *>(sender());
    for(int i = 0; i < userlist.size(); i++)
    {
        if(userlist.at(i).userfd == tobeclose)
        {
            userlist.removeAt(i);//断开连接则删除链表中相关的用户信息
        }
    }
    tobeclose->deleteLater();
    brodcastNewclient(nullptr);
}

// 处理所有未读信息
void server::handleread()
{
    QTcpSocket *toberead = qobject_cast<QTcpSocket *>(sender());
    QByteArray buf = toberead->readAll();
    QJsonDocument req_js = QJsonDocument::fromJson(buf);

//    if(!req_js.isObject())
//    {
//        qDebug() << __FILE__ << __FUNCTION__ << "未知请求:" << buf;
//        return;
//    }
    QJsonObject req_obj = req_js.object();

    QString req_type = req_obj.value("command").toString();

    if(req_type == "user_signin")
    {
        qDebug() << "用户正在登录";
        handle_signin(toberead, req_obj);
    }
    if(req_type == "user_signup")
    {
        qDebug() << "用户正在注册";
        handle_signup(toberead, req_obj);
    }
    if(req_type == "getfriendslist")
    {
        qDebug() << "用户正在刷新好友列表";
        handle_getfriendslist(toberead);
    }
    if(req_type == "sendmessage")
    {
        qDebug() << "用户正在发送信息";
        handle_sendmessage(toberead, req_obj);
    }
    if(req_type == "findpasswd")
    {
        qDebug() << "用户正在找回密码";
        handle_findpasswd(toberead, req_obj);
    }
    if(req_type == "cancel_signin")
    {
        qDebug() << "用户取消登录";
        handle_cancel_signin(toberead);
    }
}
